<?php


namespace common\service;

use common\model\DelayOrderTaskStepCategoryConfirmModel;
use common\model\EntityModel;
use common\model\ProjectMemberModel;
use common\model\ProjectStepCategoryConfirmConfigModel;
use common\model\StepCategoryModel;
use common\model\TagRelationModel;
use common\model\TaskModel;
use support\SingletonTrait;
use common\model\DelayOrderTaskModel;

/**
 * 延期服务
 */
class DelayOrderTaskService
{
    use SingletonTrait;

    protected DelayOrderTaskModel $delayOrderTaskModel;

    //延期任务类型(申请延期 request_delay, 今日完成 today_done,需求单 demand_order,工单 work_order)
    const TYPE_REQUEST_DELAY = '申请延期';
    const TYPE_TODAY_DONE = '今日完成';
    const TYPE_DEMAND_ORDER = '需求单';
    const TYPE_WORK_ORDER = '工单';

    public $typeInfo
        = [
            self::TYPE_REQUEST_DELAY, self::TYPE_TODAY_DONE, self::TYPE_DEMAND_ORDER, self::TYPE_WORK_ORDER,
        ];


    public function __construct()
    {
        $this->delayOrderTaskModel = model(DelayOrderTaskModel::class);
    }

    /**
     * 根据任务id获取延期单数据
     */
    public function getDelayOrderListByTaskId($taskId)
    {
        $field = [
            "a.id", 'do.id as delay_order_id', 'do.confirm_status', "a.step_category_confirmed", 'a.created_by', "a.created", "a.manager_confirmed", "a.confirming_step_category_id", "u.phone",
            "u.name as user_name", "a.original_plan_time", "a.plan_delivery_time", "a.delay_time", "a.step_category_id", "sc_info.name as step_category_name", "a.type", "a.project_id", "a.task_id",
            "a.delay_time", "a.delay_reason", "a.created_by", "sc.name as confirming_step_category_name",
        ];

        $data = model(DelayOrderTaskModel::class)->alias('a')->field($field)->join('step_category sc on sc.id = a.confirming_step_category_id', 'left')->join(
            'step_category sc_info  on sc_info.id = a.step_category_id', 'left'
        )->join('delay_order  do on do.id = a.delay_order_id', 'left')->join('user u on u.id = a.created_by')->where(['task_id' => $taskId])->select();

        if (empty($data)) {
            return [];
        }

        foreach ($data as $key => &$val) {

            switch ($val['type']) {
                case 'request_delay':
                    $val['type_info'] = $this->typeInfo[0];
                    break;
                case 'today_done':
                    $val['type_info'] = $this->typeInfo[1];
                    break;
                case 'demand_order':
                    $val['type_info'] = $this->typeInfo[2];
                    break;
                case 'work_order':
                    $val['type_info'] = $this->typeInfo[3];
                    break;
            }

        }

        return $data;
    }

    /**
     * 按项目、集、环节，分组获取我参与确认的延期统计
     * 分页：集
     *
     * @param array  $page
     * @param array  $projectIds 项目id
     * @param array  $episodeCodes 剧集code
     * @param array  $stepCategoryIds 环节ids
     * @param string $delayCode 延期包类型， 资产、镜头、标准
     * @param array  $timeScope 时间范围
     * @param string $taskName 任务名搜索
     *
     * @return array
     */
    public function getDelayOrderTaskGrouped(
        string $queryType = "count", int $countLimit = 100, array $page = [], array $projectIds = [], array $episodeCodes = [], array $stepCategoryIds = [], array $delayCode = [],
        array  $timeScope = [], string $taskName = ""
    ): array
    {
        $userId = \request()->getUserId();
        // 一、查询我能确认的项目、环节，以及我是制片的项目
        $userCanConfirmStepCategoryIdList = ProjectStepCategoryConfirmConfigService::getInstance()->getUserCanConfirmStepCategoryIdList(['GT', 0], $userId, 'delay', 'project_id,step_category_id');
        $userCanConfirmProjectIds = array_column($userCanConfirmStepCategoryIdList, 'project_id');
        $userCanConfirmStepCategoryIdList = array_group_by($userCanConfirmStepCategoryIdList, 'project_id');
        $iCanConfirmStepCategoryIdMap = [];
        foreach ($userCanConfirmStepCategoryIdList as $projectId => $config) {
            $iCanConfirmStepCategoryIdMap[$projectId] = array_column($config, 'step_category_id');
        }

        $projectIdListProducer = model(ProjectMemberModel::class)->where([
            'user_id' => $userId, 'role_code' => 'executive_producer', 'is_delete' => 0,
        ])->field('project_id')->select();
        $userProducerProjectIds = array_column($projectIdListProducer, 'project_id');
        $userProjectIds = array_unique(array_merge($userCanConfirmProjectIds, $userProducerProjectIds));
        if (empty($userProjectIds)) {
            return [];
        }

        //  二、查我能确认、我参与确认的
        // 前提   这些延期记录， 必须有我能 确认的环节，或着我已经确认过，或者我是制片而能看全部环节
        $dbQuery = model(DelayOrderTaskModel::class)->join('task on task.id = delay_order_task.task_id')->join('entity on entity.id = task.entity_id', 'left')->join(
            'entity episode on episode.id = delay_order_task.episode_id', 'left'
        )->join('module on module.id = entity.module_id', 'left')->join('step_category on step_category.id = delay_order_task.step_category_id', 'left')->join(
            'project on project.id = delay_order_task.project_id', 'left'
        )->join('delay_order_task_step_category_confirm dotscc on dotscc.delay_order_task_id = delay_order_task.id');
        // 1. 组装筛选条件
        $filter = [
            'delay_order_task.manager_confirmed' => 'default',
            // 同租户
        ];
        if (!empty($projectIds)) {
            $filter['delay_order_task.project_id'] = ['in', $projectIds];
            $userProjectIds = array_intersect($userProjectIds, $projectIds);
        }
        if (!empty($episodeCodes)) {
            $filter['episode.code'] = ['in', $episodeCodes];
        }
        if (!empty($stepCategoryIds)) {
            $filter['delay_order_task.step_category_id'] = ['in', $stepCategoryIds];
        }
        if (!empty($timeScope)) {
            $filter['delay_order_task.created'] = ['between', $timeScope];
        }
        if (!empty($taskName)) {
            $filter['task.name'] = ['like', "%" . $taskName . "%"];
        }
        if (!empty($delayCode)) {
            $delayCodeFilter = [];
            if (in_array('asset', $delayCode) || in_array('shot', $delayCode)) {
                $delayCodeFilter[] = [
                    'task.step_type' => 'step', 'module.code' => ['in', $delayCode],
                ];
            }
            if (in_array('standard', $delayCode)) {
                $delayCodeFilter['task.step_type'] = ['in', 'standard_meeting,standard_review'];
            }
            if (count($delayCodeFilter) > 1) {
                $delayCodeFilter['_logic'] = 'or';
            }
            $filter[] = $delayCodeFilter;
        }
        // 已确认过和我能确认并激活的环节
        // 制片，我是制片的项目里不需要限制环节
        //        $filter [] = [
        //            '_logic' => 'or',
        //            'dotscc.is_active' => 'yes',
        //            'dotscc.is_confirmed' => 'yes'
        //        ];
        $stepCategoryFilter = [//            ['dotscc.confirm_user_id' => $userId]
        ];
        foreach ($userProjectIds as $projectId) {
            $tempFilter = [];
            if (in_array($projectId, $userProducerProjectIds)) {
                $tempFilter[] = ['confirm_status' => 'producer_confirming'];
            }
            if (!empty($iCanConfirmStepCategoryIdMap[$projectId] ?? [])) {
                $tempFilter[] = [
                    'confirm_status' => 'step_category_confirming', 'dotscc.is_active' => 'yes', 'dotscc.step_category_id' => ['IN', $iCanConfirmStepCategoryIdMap[$projectId]],
                ];
            }
            if (count($tempFilter) > 1) {
                $tempFilter['_logic'] = 'or';
            }
            $stepCategoryFilter[] = ['delay_order_task.project_id' => $projectId, $tempFilter];
        }
        if (count($stepCategoryFilter) > 1) {
            $stepCategoryFilter['_logic'] = 'or';
        }
        if (!empty($stepCategoryFilter)) {
            $filter[] = $stepCategoryFilter;
        }
        $dbQuery = $dbQuery->where($filter);
        // 2. 组织查询字段
        if ($queryType == "list") {
            $fields = [
                'count(distinct delay_order_task.id) as count', 'delay_order_task.project_id', 'project.name as project_name', 'delay_order_task.episode_id', 'episode.code as episode_code',
                'group_concat(distinct task.step_type) as step_type_list', 'entity.module_id', 'module.code as module_code',

                // 发起环节
                'delay_order_task.step_category_id as step_category_id', 'step_category.code as step_category_code', 'step_category.name as step_category_name',
                //            '"" as all_step_category_list',
                //            '"" as not_confirmed_step_category_list',
            ];
            $dbQuery = $dbQuery->page(...$page);

        } else {
            $fields = [
                'count(distinct delay_order_task.id) as count',
            ];
            $dbQuery = $dbQuery->limit($countLimit);
        }
        // 根据项目、剧集、发起环节分组并分页
        $res = $dbQuery->field($fields)->group(
            'delay_order_task.episode_id, delay_order_task.step_category_id, if(find_in_set(ifnull(module.code, "standard"), "asset,level,design"), "asset", ifnull(module.code, "standard"))'
        )->select();

        if ($queryType == "list") {
            $stepCategoryList = [];
            if (!empty($res)) {
                $stepCategoryList = model(StepCategoryModel::class)->where(['id' => ['in', array_unique(array_column($res, 'step_category_id'))]])->field('id, name, code')->select();
            }
            foreach ($res as &$item) {
                if (in_array($item['module_code'], ['asset', 'level', 'design'])) {
                    $item['module_code'] = 'asset';
                }
            }

            return [
                'delay_package_list' => $res, 'step_category_list' => $stepCategoryList,
            ];
        } else {
            return [
                'count' => count($res),
            ];
        }
    }

    /**
     * @param $projectId
     * @param $userId
     * @param $stepCategoryId
     * @param $type
     *
     * @return array|false|mixed|string|null
     */
    public function checkStepCategoryIdForUserInfo($projectId, $userId, $stepCategoryId, $type)
    {
        return model(ProjectStepCategoryConfirmConfigModel::class)
            ->field('id')
            ->where([
                'project_id' => $projectId,
                'confirm_user_id' => $userId,
                'type' => $type,
                'step_category_id' => $stepCategoryId
            ])
            ->find();
    }


    /**
     * 单项目延期单数据查看
     * 项目、剧集、环节必传且单一
     *
     * @param array $page
     * @param array $filter
     * @param int   $userId
     * @return array
     */
    public function getDelayOrderTaskList(array $filter, array $page, int $userId): array
    {
        //拼装查询条件
        $condition = [];
        $conditionStatus = [];
        $stepCategoryId = $filter["step_category_id"] ?? '';
        $condition["delay_order_task.episode_id"] = $filter["episode_id"];
        $condition["delay_order_task.project_id"] = $filter["project_id"];
        if (!empty($filter['delay_order_task_id'])) {
            $condition['delay_order_task.id'] = ["in", $filter['delay_order_task_id']];
        }
        //wait_for_me_confirm 我确认的 yes 审核通过 no 审核拒绝 全部条件下 confirm_status 为空
        $conditionStatusAll = [];
        $checkStepCategoryIdForUserInfo = $this->checkStepCategoryIdForUserInfo($filter['project_id'], $userId, $stepCategoryId, 'delay');
        //制片角色可以确认的数据
        $projectMemberInfo = $this->checkCanProducerInfo($filter['project_id'], $userId);

        if (!empty($filter['confirm_status'])) {
            switch ($filter['confirm_status']) {
                case "wait_for_me_confirm":
                    if (!empty($projectMemberInfo)) {
                        $conditionStatus[] = [
                            "delay_order_task.confirm_status" => "producer_confirming",
                            "delay_order_task.step_category_id" => $stepCategoryId
                        ];
                    }
                    //环节中可以确认的数据
                    if (!empty($checkStepCategoryIdForUserInfo)) {
                        $conditionStatus[] = [
                            "delay_order_task.confirm_status" => "step_category_confirming",
                            "delay_order_task_step_category_confirm.step_category_id" => $stepCategoryId,
                            "delay_order_task_step_category_confirm.is_active" => "yes",
                        ];
                    }
                    //组装制片和环节确认条件为并列关系
                    break;
                case "yes":
                    // 审核通过
                    $conditionStatus[] = [
                        "delay_order_task.confirm_status" => "yes",
                        "delay_order_task.step_category_id" => $stepCategoryId
                    ];
                    break;

                case "no":
                    // 审核拒绝
                    $conditionStatus[] = [
                        "delay_order_task.confirm_status" => "no",
                        "delay_order_task.step_category_id" => $stepCategoryId
                    ];
                    break;

                default :
                    // 全部
                    $conditionStatusAll[] = [
                        "delay_order_task.step_category_id" => $stepCategoryId,
                        "delay_order_task.confirm_status" => ["in", ["producer_confirming", "yes", "no"]]
                    ];

                    if (!empty($checkStepCategoryIdForUserInfo)) {
                        $conditionStatusAll[] = [
                            "delay_order_task.confirm_status" => "step_category_confirming",
                            "delay_order_task_step_category_confirm.step_category_id" => $stepCategoryId,
                        ];
                    }

                    break;
            }
        }
        if (count($conditionStatus) > 1) {
            $conditionStatus['_logic'] = 'or';
        }
        if (!empty($conditionStatus)) {
            $condition[] = $conditionStatus;
        }

        // 查询全部时进行判断
        if (count($conditionStatusAll) > 1) {
            $conditionStatusAll['_logic'] = 'or';
        }
        if (!empty($conditionStatusAll)) {
            $condition[] = $conditionStatusAll;
        }
        //任务名称查找
        if (!empty($filter['task_name'])) {
            $condition[] = [
                "entity.name" => trim($filter['task_name']),
                "task.name" => trim($filter['task_name']),
                "_logic" => "or",
            ];
        }
        //构建指定的延期单查询时间
        if (!empty($filter['created'])) {
            $condition['delay_order_task.created'] = ["between", $filter['created']];
        }

        if (!empty($filter['created_by'])) {
            $condition['delay_order_task.created_by'] = ['in', $filter['created_by']];
        }
        // 首次加载时间计算数量
        $total = $this->delayOrderTaskModel
            ->join('task on task.id = delay_order_task.task_id')
            ->join('entity on entity.id = task.entity_id', 'left')
            ->join('delay_order_task_step_category_confirm on delay_order_task_step_category_confirm.delay_order_task_id = delay_order_task.id', 'left')
            ->where($condition)
            ->count(
                'distinct delay_order_task.id'
            );


        // 组装数据
        $delayOrderTaskFields = [
            'delay_order_task.id', 'entity.id', 'entity.name', 'entity.code', 'entity.module_id', 'entity.initial_episode_code', 'entity.showings_number', 'task.id', 'task.step_type', 'task.step_id',
            'task.step_category_id', 'task.name', 'task.code', 'delay_order_task.id', 'delay_order_task.delay_order_id', 'delay_order_task.type',
            'delay_order_task.project_id', 'delay_order_task.task_id', 'delay_order_task.original_plan_time', 'delay_order_task.plan_delivery_time', 'delay_order_task.delay_time',
            'delay_order_task.abnormal_info', 'delay_order_task.delay_reason', 'delay_order_task.delay_reason_type', 'delay_order_task.step_category_confirmed', 'delay_order_task.manager_confirmed',
            'delay_order_task.confirm_status',
        ];

        // 查询延期单信息
        $delayOrderTaskList = model(DelayOrderTaskModel::class)
            ->join('task on task.id = delay_order_task.task_id', 'left')
            ->join('entity on entity.id = task.entity_id', 'left');
        // 当用户有环节制片时条件判断确认
        if (!empty($checkStepCategoryIdForUserInfo)) {
            $delayOrderTaskList = $delayOrderTaskList->join("delay_order_task_step_category_confirm on delay_order_task_step_category_confirm.delay_order_task_id = delay_order_task.id and delay_order_task_step_category_confirm.step_category_id = {$stepCategoryId}", 'left');
        }

        $delayOrderTaskList = $delayOrderTaskList->where($condition)
            ->field(build_complex_query_fields($delayOrderTaskFields, '__'))
            ->page(...$page)
            ->group('delay_order_task.id')
            ->select();

        if (empty($delayOrderTaskList)) {
            return [
                "rows" => [], "total" => $total,
            ];
        }

        $delayOrderTaskEntityIdList = array_column($delayOrderTaskList, 'entity__id');
        $delayOrderTaskEntityIdList = array_filter($delayOrderTaskEntityIdList, function ($i) {
            return intval($i) > 0;
        });
        $delayOrderTaskIdList = array_column($delayOrderTaskList, 'delay_order_task__id');
        //查询环节确认数据
        $delayOrderTaskStepCategoryField = [
            "dotscc.id",
            "dotscc.delay_order_id",
            "dotscc.delay_order_task_id",
            "dotscc.step_category_id",
            "dotscc.is_confirmed",
            "dotscc.is_active",
            "dotscc.need_delay",
            "dotscc.delay_to",
            "dotscc.delay_reason",
            "dotscc.step_category_type"
        ];
        $delayOrderTaskStepCategoryConfirmList = model(DelayOrderTaskStepCategoryConfirmModel::class)
            ->alias('dotscc')
            ->where(['dotscc.delay_order_task_id' => ['IN', implode(',', $delayOrderTaskIdList)]])
            ->order('dotscc.delay_order_task_id asc,id asc')
            ->field($delayOrderTaskStepCategoryField)
            ->select();


        $stepCategoryIdList = array_unique(array_column($delayOrderTaskStepCategoryConfirmList, 'step_category_id'));
        //查询环节确认时间
        $entityStepCategoryDeliveryTimeList = model(TaskModel::class)
            ->where(['entity_id' => ['IN', implode(',', $delayOrderTaskEntityIdList)],
                'step_type' => TaskModel::STEP_TYPE_STEP,
                'step_category_id' => ['IN', implode(',', $stepCategoryIdList)]
            ])
            ->field("max(plan_delivery_time) delivery_time,concat(entity_id,'#',step_category_id) uk")
            ->group("entity_id, step_category_id")
            ->select();

        $entityStepCategoryDeliveryTimeList = array_column($entityStepCategoryDeliveryTimeList, 'delivery_time', 'uk');

        $stepCategoryList = StepCategoryService::getInstance()->getList([], ["id", "name", "code", "entity_id", "is_standard", "task_type", "is_deprecate", "is_show", "is_enable_census", "show_index", "show_name"]);
        $stepCategoryList = array_column($stepCategoryList, null, 'id');
        $stepList = StepService::getInstance()->getList([], ["id", "name", "code", "color", "variable", "step_category_id", "engine", "batch", "can_multiple_submit", "need_assemble", "is_dismantle_step", "show_index"]);
        $stepList = array_column($stepList, null, 'id');

        $delayOrderTaskStepCategoryConfirmListGrouped = array_group_by($delayOrderTaskStepCategoryConfirmList, 'delay_order_task_id');

        unset($delayOrderTaskStepCategoryConfirmList);
        //处理延期单数据
        foreach ($delayOrderTaskList as &$delayOrderTask) {
            $delayOrderTask = separate_complex_query_data($delayOrderTask, '__');
            $delayOrderTask['step'] = $stepList[$delayOrderTask['task']['step_id']] ?? null;
            $delayOrderTask['step_category'] = $stepCategoryList[$delayOrderTask['task']['step_category_id']] ?? null;
            $first = true;
            // 组装延期单交付时间信息
            foreach ($delayOrderTaskStepCategoryConfirmListGrouped[$delayOrderTask['delay_order_task']['id']] ?? [] as $delayOrderTaskStepCategoryConfirm) {
                if (!isset($stepCategoryList[$delayOrderTaskStepCategoryConfirm['step_category_id']])) {
                    continue;
                }
                if ($first) {
                    $first = false;
                    $delayOrderTaskStepCategoryConfirm['type'] = $delayOrderTask['delay_order_task']['type'];
                    $delayOrderTaskStepCategoryConfirm['original_plan_time'] = $delayOrderTask['delay_order_task']['original_plan_time'];
                    $delayOrderTaskStepCategoryConfirm['plan_delivery_time'] = $delayOrderTask['delay_order_task']['plan_delivery_time'];
                    $delayOrderTaskStepCategoryConfirm['delay_time'] = $delayOrderTask['delay_order_task']['delay_time'];
                    $delayOrderTaskStepCategoryConfirm['abnormal_info'] = $delayOrderTask['delay_order_task']['abnormal_info'];
                    $delayOrderTaskStepCategoryConfirm['delay_reason'] = $delayOrderTask['delay_order_task']['delay_reason'];
                }
                $stepCategory = $stepCategoryList[$delayOrderTaskStepCategoryConfirm['step_category_id']];
                $delayOrderTaskStepCategoryConfirm['current_user_can_confirm'] = false;
                // 是我能确认的环节并且当前环节是激活的
                if ((!empty($projectMemberInfo) || !empty($checkStepCategoryIdForUserInfo)) &&
                    $delayOrderTaskStepCategoryConfirm['is_active'] === 'yes'
                ) {
                    $delayOrderTaskStepCategoryConfirm['current_user_can_confirm'] = true;
                }

                // 补充当前的计划交付时间
                $uk = sprintf("%d#%d", $delayOrderTask['entity']['id'] ?? 0, $stepCategory['id']);
                $delayOrderTaskStepCategoryConfirm['entity_step_category_plan_delivery_time'] = $entityStepCategoryDeliveryTimeList[$uk] ?? 0;
                $delayOrderTask[$stepCategory['code']] = $delayOrderTaskStepCategoryConfirm;
            }
        }

        return [
            "rows" => $delayOrderTaskList, "total" => $total,
        ];

    }


    /**
     * 判断制片是否可以确认
     * @param $projectId
     * @param $userId
     *
     * @return array
     */
    private function checkCanProducerInfo($projectId, $userId): array
    {

        $projectMemberInfo = model(ProjectMemberModel::class)
            ->where([
                'project_id' => $projectId,
                'user_id' => $userId,
                'role_code' => 'executive_producer',
                'is_delete' => 0,
            ])->find();
        if (empty($projectMemberInfo)) {
            return [];
        }
        return $projectMemberInfo;
    }

}
